home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JFileChooser.java < prev    next >
Text File  |  1998-06-30  |  31KB  |  1,017 lines

  1. /*
  2.  * @(#)JFileChooser.java    1.28 98/04/23
  3.  * 
  4.  * Copyright (c) 1997,1998 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing.preview;
  22.  
  23. import com.sun.java.swing.*;
  24. import com.sun.java.swing.event.*;
  25. import com.sun.java.swing.preview.filechooser.*;
  26. import com.sun.java.swing.plaf.FileChooserUI;
  27. import com.sun.java.accessibility.*;
  28.  
  29. import java.io.File;
  30. import java.util.Vector;
  31. import java.awt.Component;
  32. import java.awt.Container;
  33. import java.awt.BorderLayout;
  34. import java.awt.Frame;
  35. import java.awt.event.*;
  36.  
  37. /**
  38.  * JFileChooser provides a simple mechanism for the user to chooser a file.
  39.  *
  40.  * The following pops up a file chooser in the users home directory that
  41.  * only sees .jpg and .gif images:
  42.  *    JFileChooser chooser = new JFileChooser();
  43.  *    ExtensionFileFilter filter = new ExtensionFileFilter();
  44.  *    filter.addExtension("jpg");
  45.  *    filter.addExtension("gif");
  46.  *    filter.setDescription("JPG & GIF Images");
  47.  *    chooser.setFileFilter(filter);
  48.  *    int returnVal = chooser.showOpenDialog(parent);
  49.  *    if(returnVal == JFileChooser.APPROVE_OPTION) {
  50.  *       System.out.println("You chose to open this file: " +
  51.  *            chooser.getSelectedFile().getName());
  52.  *    }
  53.  *
  54.  * @version 1.28 04/23/98
  55.  * @author Jeff Dinkins
  56.  *
  57.  * // PENDING(jeff) add beaninfo
  58.  *
  59.  */
  60. public class JFileChooser extends JComponent implements Accessible {
  61.  
  62.     // ************************
  63.     // ***** Dialog Types *****
  64.     // ************************
  65.  
  66.     /**
  67.      * Type value indicating that the FileChooser supports an "Open"
  68.      * file operation.
  69.      */
  70.     public static final int OPEN_DIALOG = 0;
  71.  
  72.     /**
  73.      * Type value indicating that the FileChooser supports a "Save"
  74.      * file operation.
  75.      */
  76.     public static final int SAVE_DIALOG = 1;
  77.  
  78.     /**
  79.      * Type value indicating that the FileChooser supports a developer
  80.      * sepcified file operation.
  81.      */
  82.     public static final int CUSTOM_DIALOG = 2;
  83.  
  84.  
  85.     // ********************************
  86.     // ***** Dialog Return Values *****
  87.     // ********************************
  88.  
  89.     /**
  90.      * Return value if cancel is chosen.
  91.      */
  92.     public static final int CANCEL_OPTION = 1;
  93.  
  94.     /**
  95.      * Return value approve is chosen.
  96.      */
  97.     public static final int APPROVE_OPTION = 0;
  98.  
  99.     /**
  100.      * Return value if an error occured.
  101.      */
  102.     public static final int ERROR_OPTION = 0;
  103.  
  104.  
  105.     // **********************************
  106.     // ***** FileChooser properties *****
  107.     // **********************************
  108.  
  109.  
  110.     public static final int FILES_ONLY = 0;
  111.     public static final int DIRECTORIES_ONLY = 1;
  112.     public static final int FILES_AND_DIRECTORIES = 2;
  113.  
  114.     public static final String CANCEL_SELECTION = "CancelSelection";
  115.     public static final String APPROVE_SELECTION = "ApproveSelection";
  116.  
  117.     public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty";
  118.     public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty";
  119.  
  120.     public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
  121.     public static final String SELECTED_FILE_CHANGED_PROPERTY = "ApproveSelection";
  122.  
  123.     public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "fileFilterChanged";
  124.  
  125.     public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged";
  126.  
  127.     public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
  128.     public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged";
  129.  
  130.     public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged";
  131.  
  132.     public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged";
  133.     public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty";
  134.  
  135.     public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty";
  136.     public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty";
  137.  
  138.     // ******************************
  139.     // ***** instance variables *****
  140.     // ******************************
  141.  
  142.     private String dialogTitle = null;
  143.     private String approveButtonText = null;
  144.     private String approveButtonToolTipText = null;
  145.     private ActionListener actionListener = null;
  146.  
  147.     private Vector filters = new Vector(5);
  148.     private JDialog dialog = null;
  149.     private int dialogType = OPEN_DIALOG;
  150.     private int returnValue = ERROR_OPTION;
  151.     private JComponent accessory = null;
  152.  
  153.     private FileView fileView = null;
  154.     private FileView uiFileView = null;
  155.  
  156.     private boolean useFileHiding = true;
  157.  
  158.     private int fileSelectionMode = FILES_ONLY;
  159.  
  160.     private boolean multiSelectionEnabled = false;
  161.  
  162.     private FileFilter fileFilter = null;
  163.  
  164.     private FileSystemView fileSystemView = null;
  165.  
  166.     private File currentDirectory = null;
  167.     private File selectedFile = null;
  168.     private File[] selectedFiles;
  169.  
  170.     // *************************************
  171.     // ***** JFileChooser Constructors *****
  172.     // *************************************
  173.  
  174.     /**
  175.      * Creates a JFileChooser pointing to the user's home directory.
  176.      */
  177.     public JFileChooser() {
  178.         this((File) null);
  179.     }
  180.     
  181.     /**
  182.      * Creates a JFileChooser using the given path. Passing in a null
  183.      * string causes the file chooser to point to the users home directory.
  184.      *
  185.      * @param path  a String giving the path to a file or directory
  186.      */
  187.     public JFileChooser(String path) {
  188.     init();
  189.     setCurrentDirectory(getFileSystemView().createFileObject(path));
  190.     setFileFilter(getAcceptAllFileFilter());
  191.     }
  192.  
  193.     /**
  194.      * Creates a JFileChooser using the given File as the path. Passing
  195.      * in a null file causes the file chooser to point to the users's
  196.      * home directory.
  197.      *
  198.      * @param directory  a File object specifying the path to a file 
  199.      *                   or directory
  200.      */
  201.     public JFileChooser(File directory) {
  202.     init();
  203.     setCurrentDirectory(directory);
  204.     setFileFilter(getAcceptAllFileFilter());
  205.     }
  206.  
  207.     // common initialization
  208.     protected void init() {
  209.     setFileSystemView(FileSystemView.getFileSystemView());
  210.         updateUI();
  211.     }
  212.  
  213.     // *****************************
  214.     // ****** File Operations ******
  215.     // *****************************
  216.  
  217.     /**
  218.      * Returns the selected file. This can be set either by the
  219.      * programmer via setFile() or by a user action, such as
  220.      * either typing the filename int the UI or selecting the
  221.      * file from a list in the UI.
  222.      *
  223.      * @return the selected file
  224.      */
  225.     public File getSelectedFile() {
  226.     return selectedFile;
  227.     }
  228.  
  229.     /**
  230.      * Sets the selected file. If the file's parent directory is
  231.      * not the current directory, it changed the current directory
  232.      * to be the files parent directory.
  233.      *
  234.      * @see #getSelectedFile();
  235.      *
  236.      * @param selectedFile the selected file 
  237.      */
  238.     public void setSelectedFile(File selectedFile) {
  239.     // PENDING(jeff) - make sure that the file's path is
  240.     // in the current directory. If not, change the current
  241.     // directory to the file's path. 
  242.     File oldValue = this.selectedFile;
  243.     this.selectedFile = selectedFile;
  244.     ensureFileIsVisible(selectedFile);
  245.     firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue, this.selectedFile);
  246.     }
  247.  
  248.     /**
  249.      * Returns a list of selected files if the filechooser is
  250.      * set to allow multi-selection.
  251.      */
  252.     public File[] getSelectedFiles() {
  253.     if(selectedFiles == null) {
  254.         return new File[0];
  255.     } else {
  256.         return (File[]) selectedFiles.clone();
  257.     }
  258.     }
  259.  
  260.     /**
  261.      * Sets the list of selected files if the filechooser is
  262.      * set to allow multi-selection.
  263.      */
  264.     // PENDING(jeff) Add propertychanged event
  265.     public void setSelectedFiles(File[] selectedFiles) {
  266.     this.selectedFiles = selectedFiles;
  267.     }
  268.  
  269.     /**
  270.      * Returns the current directory. 
  271.      *
  272.      * @return the current directory
  273.      * @see #setCurrentDirectory
  274.      */
  275.     public File getCurrentDirectory() {
  276.     return currentDirectory;
  277.     }
  278.  
  279.     /**
  280.      * Sets the current directory. Passing in null sets the filechooser
  281.      * to point to the users's home directory.
  282.      *
  283.      * If the file passed in as currentDirectory is not a directory, the
  284.      * parent of the file will be used as the currentDirectory. If the
  285.      * parent is not traversable, then it will walk up the parent tree
  286.      * until it finds a traversable direcotry, or hits the root of the
  287.      * file system.
  288.      *
  289.      * @param currentDirectory the current directory to point to
  290.      * @see #getCurrentDirectory
  291.      */
  292.     public void setCurrentDirectory(File dir) {
  293.     if((this.currentDirectory == dir) && (dir != null)) {
  294.         return;
  295.     }
  296.  
  297.     File oldValue = this.currentDirectory;
  298.  
  299.     if(dir == null) {
  300.         this.currentDirectory = getFileSystemView().createFileObject(System.getProperty("user.home"));
  301.     } else {
  302.         File prev = null;
  303.         while(!isTraversable(dir) && prev != dir && !getFileSystemView().isRoot(dir)) {
  304.         prev = dir;
  305.         dir = getFileSystemView().getParentDirectory(dir);
  306.         }
  307.         this.currentDirectory = dir;
  308.     }
  309.  
  310.     firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue, this.currentDirectory);
  311.     }
  312.  
  313.     /**
  314.      * Changes the directory to be set to the parent of the
  315.      * current directory. 
  316.      *
  317.      * @see #getCurrentDirectory
  318.      */
  319.     public void changeToParentDirectory() {
  320.     File oldValue = getCurrentDirectory();
  321.     setCurrentDirectory(getFileSystemView().getParentDirectory(oldValue));
  322.     }
  323.  
  324.     /**
  325.      * Tells the UI to rescan it's files list from the current directory.
  326.      */
  327.     public void rescanCurrentDirectory() {
  328.         getUI().rescanCurrentDirectory();
  329.     }
  330.  
  331.     public void ensureFileIsVisible(File f) {
  332.         getUI().ensureFileIsVisible(f);
  333.     }
  334.  
  335.     // **************************************
  336.     // ***** FileChooser Dialog methods *****
  337.     // **************************************
  338.  
  339.     /**
  340.      * Pops up an "Open File" file chooser dialog.
  341.      *
  342.      * @return   the return state of the filechooser on popdown:
  343.      *             CANCEL_OPTION, APPROVE_OPTION
  344.      */
  345.     public int showOpenDialog(Component parent) {
  346.     setDialogType(OPEN_DIALOG);
  347.     return showDialog(parent, null);
  348.     }
  349.  
  350.     /**
  351.      * Pops up a "Save File" file chooser dialog.
  352.      *
  353.      * @return   the return state of the filechooser on popdown:
  354.      *             CANCEL_OPTION, APPROVE_OPTION
  355.      */
  356.     public int showSaveDialog(Component parent) {
  357.     setDialogType(SAVE_DIALOG);
  358.     return showDialog(parent, null);
  359.     }
  360.  
  361.     /**
  362.      * Pops a custom file chooser dialog with a custom ApproveButton.
  363.      * e.g. filechooser.showDialog(parentWindow, "Run Application"
  364.      * would pop up a filechooser with a "Run Application" button
  365.      * instead of the normal "Save" or "Open" button.
  366.      *
  367.      * @param   approveButtonText the text of the ApproveButton
  368.      * @return  the return state of the filechooser on popdown:
  369.      *             CANCEL_OPTION, APPROVE_OPTION
  370.      */
  371.     public int showDialog(Component parent, String approveButtonText) {
  372.     if(approveButtonText != null) {
  373.         setApproveButtonText(approveButtonText);
  374.     }
  375.  
  376.         Frame frame = parent instanceof Frame ? (Frame) parent
  377.               : (Frame)SwingUtilities.getAncestorOfClass(Frame.class, parent);
  378.  
  379.     // PENDING(jeff) - make sure that ui sets initial dialog title
  380.         dialog = new JDialog(frame, getDialogTitle(), true);
  381.         Container contentPane = dialog.getContentPane();
  382.         contentPane.setLayout(new BorderLayout());
  383.         contentPane.add(this, BorderLayout.CENTER);
  384.  
  385.         dialog.pack();
  386.         dialog.setLocationRelativeTo(parent);
  387.  
  388.         dialog.show();
  389.     return returnValue;
  390.     }
  391.  
  392.     // **************************
  393.     // ***** Dialog Options *****
  394.     // **************************
  395.  
  396.     /**
  397.      * Returns the type of this dialog.
  398.      *
  399.      * @return   the type of dialog to be displayed:
  400.      *           OPEN_DIALOG, SAVE_DIALOG, CUSTOM_DIALOG
  401.      *
  402.      * @see #setDialogType
  403.      */
  404.     public int getDialogType() {
  405.     return dialogType;
  406.     }
  407.  
  408.     /**
  409.      * Sets the type of this dialog. Use OPEN_DIALOG when you want to
  410.      * bring up a filechooser that the user can use to open a file. Likewise,
  411.      * use SAVE_DIALOG for letting the user choose a file for saving.
  412.      *
  413.      * Use CUSTOM_DIALOG when you want to use the filechooser in a context
  414.      * other than "Open" or "Save". For instance, you might want to bring up
  415.      * a filechooser that allows the user to choose a file to execute. Note that
  416.      * you normally would not need to set the FileChooser to use CUSTOM_DIALOG
  417.      * since a call to setApproveButtonText does this for you.
  418.      *
  419.      * @param dialogType the type of dialog to be displayed:
  420.      *                   OPEN_DIALOG, SAVE_DIALOG, CUSTOM_DIALOG
  421.      *
  422.      * @see #getDialogType
  423.      * @see #setApproveButtonText
  424.      */ 
  425.     // PENDING(jeff) - fire button text change property
  426.     public void setDialogType(int dialogType) {
  427.     if(this.dialogType == dialogType) {
  428.         return;
  429.     }
  430.     if(!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) {
  431.         throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType);
  432.     }
  433.     int oldValue = this.dialogType;
  434.     this.dialogType = dialogType;
  435.     if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) {
  436.         setApproveButtonText(null);
  437.     }
  438.     firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType);
  439.     }
  440.  
  441.     /**
  442.      * Sets the string that goes in the FileChooser window's title bar.
  443.      *
  444.      * @see #getDialogTitle
  445.      */
  446.     public void setDialogTitle(String dialogTitle) {
  447.     this.dialogTitle = dialogTitle;
  448.     if(dialog != null) {
  449.         dialog.setTitle(dialogTitle);
  450.     }
  451.     }
  452.  
  453.     /**
  454.      * Gets the string that goes in the FileChooser's titlebar.
  455.      *
  456.      * @see #setDialogTitle
  457.      */
  458.     public String getDialogTitle() {
  459.     return dialogTitle;
  460.     }
  461.  
  462.     // ************************************
  463.     // ***** FileChooser View Options *****
  464.     // ************************************
  465.  
  466.  
  467.  
  468.     /**
  469.      * Sets the tooltip text used in the ApproveButton.
  470.      * If null, the UI object will determine the button's text.
  471.      *
  472.      * @return the text used in the ApproveButton
  473.      *
  474.      * @see #setApproveButtonText
  475.      * @see #setDialogType
  476.      * @see #showDialog
  477.      */ 
  478.     public void setApproveButtonToolTipText(String toolTipText) {
  479.     if(approveButtonToolTipText == toolTipText) {
  480.         return;
  481.     }
  482.     String oldValue = approveButtonToolTipText;
  483.     approveButtonToolTipText = toolTipText;
  484.     setDialogType(CUSTOM_DIALOG);
  485.     firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText);
  486.     }
  487.  
  488.     /**
  489.      * Returns the tooltip text used in the ApproveButton.
  490.      * If null, the UI object will determine the button's text.
  491.      *
  492.      * @return the text used in the ApproveButton
  493.      *
  494.      * @see #setApproveButtonText
  495.      * @see #setDialogType
  496.      * @see #showDialog
  497.      */ 
  498.     public String getApproveButtonToolTipText() {
  499.     return approveButtonToolTipText;
  500.     }
  501.  
  502.     /**
  503.      * Sets the text used in the ApproveButton in the FileChooserUI.
  504.      *
  505.      * @param approveButtonText the text used in the ApproveButton
  506.      *
  507.      * @see #getApproveButtonText
  508.      * @see #setDialogType
  509.      * @see #showDialog
  510.      */ 
  511.     // PENDING(jeff) - have ui set this on dialog type change
  512.     public void setApproveButtonText(String approveButtonText) {
  513.     if(this.approveButtonText == approveButtonText) {
  514.         return;
  515.     }
  516.     String oldValue = this.approveButtonText;
  517.     this.approveButtonText = approveButtonText;
  518.     setDialogType(CUSTOM_DIALOG);
  519.     firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText);
  520.     }
  521.  
  522.     /**
  523.      * Returns the text used in the ApproveButton in the FileChooserUI.
  524.      * If null, the UI object will determine the button's text.
  525.      *
  526.      * Typically, this would be "Open" or "Save".
  527.      *
  528.      * @return the text used in the ApproveButton
  529.      *
  530.      * @see #setApproveButtonText
  531.      * @see #setDialogType
  532.      * @see #showDialog
  533.      */ 
  534.     public String getApproveButtonText() {
  535.     return approveButtonText;
  536.     }
  537.  
  538.     /**
  539.      * Gets the list of user choosable file filters
  540.      *
  541.      * @return a FileFilter array containing all the choosable
  542.      *         file filters
  543.      *
  544.      * @ see #addChoosableFileFilter
  545.      * @ see #removeChoosableFileFilter
  546.      * @ see #resetChoosableFileFilter
  547.      */ 
  548.     public FileFilter[] getChoosableFileFilters() {
  549.     FileFilter[] filterArray = new FileFilter[filters.size()];
  550.     filters.copyInto(filterArray);
  551.     return filterArray;
  552.     }
  553.  
  554.     /**
  555.      * Adds a filter to the list of user choosable file filters.
  556.      * 
  557.      * @param filter the FileFilter to add to the choosable file
  558.      *               filter list
  559.      *
  560.      * @ see #getChoosableFileFilter
  561.      * @ see #removeChoosableFileFilter
  562.      * @ see #resetChoosableFileFilter
  563.      */ 
  564.     public void addChoosableFileFilter(FileFilter filter) {
  565.     if(!filters.contains(filter)) {
  566.         FileFilter[] oldValue = getChoosableFileFilters();
  567.         filters.addElement(filter);
  568.         firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
  569.     } 
  570.     }
  571.  
  572.     /**
  573.      * Removes a filter from the list of user choosable file filters. Returns
  574.      * true if the file filter was removed;
  575.      *
  576.      * @ see #addChoosableFileFilter
  577.      * @ see #getChoosableFileFilter
  578.      * @ see #resetChoosableFileFilter
  579.      */ 
  580.     public boolean removeChoosableFileFilter(FileFilter f) {
  581.     if(filters.contains(f)) {
  582.         FileFilter[] oldValue = getChoosableFileFilters();
  583.         filters.removeElement(f);
  584.         firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
  585.         return true;
  586.     } else {
  587.         return false;
  588.     }
  589.     }
  590.  
  591.     /**
  592.      * Resets the choosable file filter list to it's starting state. Normally,
  593.      * this removes all added file filters while leaving the AcceptAll file filter.
  594.      *
  595.      * @see #addChoosableFileFilter
  596.      * @see #getChoosableFileFilter
  597.      * @see #removeChoosableFileFilter
  598.      */
  599.     public void resetChoosableFileFilters() {
  600.     FileFilter[] oldValue = getChoosableFileFilters();
  601.     filters.removeAllElements();
  602.     filters.addElement(getAcceptAllFileFilter());
  603.     firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
  604.     }
  605.  
  606.     /**
  607.      * Returns the AcceptAll file filter (e.g. (All Files *.*) on windows).
  608.      */
  609.     public FileFilter getAcceptAllFileFilter() {
  610.     FileFilter filter = null;
  611.     if(getUI() != null) {
  612.         filter = getUI().getAcceptAllFileFilter();
  613.     }
  614.     return filter;
  615.     }
  616.  
  617.     /**
  618.      * Return the accessory component.
  619.      *
  620.      * @return this JFileChooser's accessory component, or null
  621.      * @see #setAccessory
  622.      */
  623.     public JComponent getAccessory() {
  624.         return accessory;
  625.     }
  626.  
  627.     /**
  628.      * Sets the accessory component. An accessory is often used to show a preview
  629.      * image of the selected file; however, it can be used for anything that
  630.      * the programmer wishes - such as extra custom file chooser controls.
  631.      *
  632.      * Note: if there was a previous accessory, you should unregister
  633.      * any listeners that the accessory might have registered with the
  634.      * file chooser.
  635.      */
  636.     public void setAccessory(JComponent newAccessory) {
  637.         JComponent oldValue = accessory;
  638.         accessory = newAccessory;
  639.     firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory);
  640.     }
  641.     
  642.     /**
  643.      * Sets the FileChooser to allow the user to just select files, just select
  644.      * directories, or select both files and directetories.
  645.      *
  646.      * @param dialogType the type of dialog to be displayed:
  647.      *                   FILES_ONLY, DIRECTORIES_ONLY, FILES_AND_DIRECTORIES
  648.      *
  649.      * @see #getFileSelectionMode
  650.      */
  651.     public void setFileSelectionMode(int mode) {
  652.     if(fileSelectionMode == mode) {
  653.         return;
  654.     }
  655.     int oldValue = fileSelectionMode;
  656.     fileSelectionMode = mode;
  657.     firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode);
  658.     }
  659.  
  660.     /**
  661.      * @see #setFileSelectionMode
  662.      */
  663.     public int getFileSelectionMode() {
  664.     return fileSelectionMode;
  665.     }
  666.  
  667.     /**
  668.      * Convenience call that determines if files are selectable based on the current
  669.      * file selection mode
  670.      *
  671.      * @see #setFileSelectionMode
  672.      * @see #getFileSelectionMode
  673.      */
  674.     public boolean isFileSelectionEnabled() {
  675.     return ((fileSelectionMode == FILES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
  676.     }
  677.  
  678.     /**
  679.      * Convenience call that determines if directories are selectable based on the current
  680.      * file selection mode
  681.      *
  682.      * @see #setFileSelectionMode
  683.      * @see #getFileSelectionMode
  684.      */
  685.     public boolean isDirectorySelectionEnabled() {
  686.     return ((fileSelectionMode == DIRECTORIES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
  687.     }
  688.  
  689.     /**
  690.      * Sets the filechooser to allow multiple file selections.
  691.      * NOTE: this functionality is not yet implemented in the current L&Fs.
  692.      *
  693.      * @see #isMultiSelectionEnabled
  694.      */
  695.     public void setMultiSelectionEnabled(boolean b) {
  696.     if(multiSelectionEnabled == b) {
  697.         return;
  698.     }
  699.     boolean oldValue = multiSelectionEnabled;
  700.     multiSelectionEnabled = b;
  701.     firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY, oldValue, multiSelectionEnabled);
  702.     }
  703.  
  704.     /**
  705.      * @see #setMultiSelectionEnabled
  706.      */
  707.     public boolean isMultiSelectionEnabled() {
  708.     return multiSelectionEnabled;
  709.     }
  710.  
  711.     
  712.     /**
  713.      * If true, hidden files are not shown in the filechooser
  714.      *
  715.      * @return the status of the file hiding property
  716.      * @see #setFileHidingEnabled
  717.      */
  718.     public boolean isFileHidingEnabled() {
  719.     return useFileHiding;
  720.     }
  721.  
  722.     /**
  723.      * Sets file hiding on or off. If true, hidden files are not shown
  724.      * in the filechooser. The job of determining which files are
  725.      * show is done by the FileView.
  726.      *
  727.      * @param b the boolean value that determines whether file hiding is
  728.      *          turned on or not.
  729.      * @see #isFileHidingEnabled
  730.      */
  731.     public void setFileHidingEnabled(boolean b) {
  732.     boolean oldValue = useFileHiding;
  733.     useFileHiding = b;
  734.     firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding);
  735.     }
  736.  
  737.     /**
  738.      * Sets the current File Filter. The file filter is used by the
  739.      * filechooser to filter out files from view from the user.
  740.      *
  741.      * @param filter the new current file filter to use
  742.      * @see #getFilefilter
  743.      */
  744.     public void setFileFilter(FileFilter filter) {
  745.     FileFilter oldValue = fileFilter;
  746.     fileFilter = filter;
  747.     firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
  748.     }
  749.     
  750.  
  751.     /**
  752.      * Returns the currently selected file filter.
  753.      *
  754.      * @return the current file filter.
  755.      * @see #setFileFilter
  756.      * @see #addChoosableFileFilter
  757.      */
  758.     public FileFilter getFileFilter() {
  759.     return fileFilter;
  760.     }
  761.  
  762.     /**
  763.      * Sets the file view to used to retrieve UI information, such as
  764.      * the icon that represents a file or the type description of a file.
  765.      *
  766.      * @see #getFileView
  767.      */
  768.     public void setFileView(FileView fileView) {
  769.     FileView oldValue = this.fileView;
  770.     this.fileView = fileView;
  771.     firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue, fileView);
  772.     }
  773.  
  774.     /**
  775.      * Returns the current file view.
  776.      *
  777.      * @see #setFileView
  778.      */
  779.     public FileView getFileView() {
  780.     return fileView;
  781.     }
  782.     
  783.     // ******************************
  784.     // *****FileView delegation *****
  785.     // ******************************
  786.  
  787.     // NOTE: all of the following methods attempt to delegate
  788.     // first to the client set fileView, and if null is returned
  789.     // (or there is now client defined fileView) then calls the
  790.     // UI's default fileView.
  791.     
  792.     /**
  793.      * @see FileView#getName
  794.      */
  795.     public String getName(File f) {
  796.     String filename = null;
  797.     if(getFileView() != null) {
  798.         filename = getFileView().getName(f);
  799.     }
  800.     if(filename == null && uiFileView != null) {
  801.         filename = uiFileView.getName(f);
  802.     }
  803.     return filename;
  804.     }
  805.  
  806.     /**
  807.      * @see FileView#getDescription
  808.      */
  809.     public String getDescription(File f) {
  810.     String description = null;
  811.     if(getFileView() != null) {
  812.         description = getFileView().getDescription(f);
  813.     }
  814.     if(description == null && uiFileView != null) {
  815.         description = uiFileView.getDescription(f);
  816.     }
  817.     return description;
  818.     }
  819.  
  820.     /**
  821.      * @see FileView#getTypeDescription
  822.      */
  823.     public String getTypeDescription(File f) {
  824.     String typeDescription = null;
  825.     if(getFileView() != null) {
  826.         typeDescription = getFileView().getTypeDescription(f);
  827.     }
  828.     if(typeDescription == null && uiFileView != null) {
  829.         typeDescription = uiFileView.getTypeDescription(f);
  830.     }
  831.     return typeDescription;
  832.     }
  833.  
  834.     /**
  835.      * @see FileView#getIconDescription
  836.      */
  837.     public Icon getIcon(File f) {
  838.     Icon icon = null;
  839.     if(getFileView() != null) {
  840.         icon = getFileView().getIcon(f);
  841.     }
  842.     if(icon == null && uiFileView != null) {
  843.         icon = uiFileView.getIcon(f);
  844.     }
  845.     return icon;
  846.     }
  847.  
  848.     /**
  849.      * @see FileView#isTraversable
  850.      */
  851.     public boolean isTraversable(File f) {
  852.     Boolean traversable = null;
  853.     if(getFileView() != null) {
  854.         traversable = getFileView().isTraversable(f);
  855.     }
  856.     if(traversable == null && uiFileView != null) {
  857.         traversable = uiFileView.isTraversable(f);
  858.     }
  859.     if(traversable == null && f != null) {
  860.         if(f.isDirectory()) {
  861.         traversable = Boolean.TRUE;
  862.         } else {
  863.         traversable = Boolean.FALSE;
  864.         }
  865.     } else if(traversable == null) {
  866.         return false;
  867.     }
  868.     return traversable.booleanValue();
  869.     }
  870.  
  871.     /**
  872.      * @see FileFilter#accept
  873.      */
  874.     public boolean accept(File f) {
  875.     boolean shown = true;
  876.     if(fileFilter != null) {
  877.         shown = fileFilter.accept(f);
  878.     }
  879.     return shown;
  880.     }
  881.  
  882.     /**
  883.      * Sets the file system view which the JFileChooser uses to
  884.      * access and create file system resouces, such as finding
  885.      * the floppy drive and getting a list of root drives.
  886.      *
  887.      * @see FileSystemView
  888.      */
  889.     public void setFileSystemView(FileSystemView fileSystemView) {
  890.     FileSystemView oldValue = this.fileSystemView;
  891.     this.fileSystemView = fileSystemView;
  892.     firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView);
  893.     }
  894.  
  895.     /**
  896.      * @see setfileSystemView
  897.      */
  898.     public FileSystemView getFileSystemView() {
  899.     return fileSystemView;
  900.     }
  901.  
  902.     // **************************
  903.     // ***** Event Handling *****
  904.     // **************************
  905.  
  906.     /**
  907.      * Called by the UI when the user hits the approve
  908.      * (AKA "Open" or "Save") button. This can also by
  909.      * called by the programmer.
  910.      */
  911.     public void approveSelection() {
  912.     returnValue = APPROVE_OPTION;
  913.     if(dialog != null) {
  914.         dialog.setVisible(false);
  915.     }
  916.     fireActionPerformed(APPROVE_SELECTION);
  917.     }
  918.  
  919.     /**
  920.      * Called by the UI when the user hits the cancel button.
  921.      * This can also be called by the programmer.
  922.      */
  923.     public void cancelSelection() {
  924.     returnValue = CANCEL_OPTION;
  925.     if(dialog != null) {
  926.         dialog.setVisible(false);
  927.     }
  928.     fireActionPerformed(CANCEL_SELECTION);
  929.     }
  930.  
  931.     /**
  932.      * adds an ActionListener to the button
  933.      */
  934.     public void addActionListener(ActionListener l) {
  935.         listenerList.add(ActionListener.class, l);
  936.     }
  937.  
  938.     /**
  939.      * removes an ActionListener from the button
  940.      */
  941.     public void removeActionListener(ActionListener l) {
  942.         listenerList.remove(ActionListener.class, l);
  943.     }
  944.  
  945.     /**
  946.      * Notify all listeners that have registered interest for
  947.      * notification on this event type. The event instance
  948.      * is lazily created using the parameters passed into
  949.      * the fire method.
  950.      * @see EventListenerList
  951.      */
  952.     protected void fireActionPerformed(String command) {
  953.         // Guaranteed to return a non-null array
  954.         Object[] listeners = listenerList.getListenerList();
  955.         ActionEvent e = null;
  956.         // Process the listeners last to first, notifying
  957.         // those that are interested in this event
  958.         for (int i = listeners.length-2; i>=0; i-=2) {
  959.             if (listeners[i]==ActionListener.class) {
  960.                 // Lazily create the event:
  961.                 if (e == null) {
  962.                     e = new ActionEvent(this,
  963.                                         ActionEvent.ACTION_PERFORMED,
  964.                                         command);
  965.                 }
  966.                 ((ActionListener)listeners[i+1]).actionPerformed(e);
  967.             }
  968.         }
  969.     }
  970.  
  971.     // *********************************
  972.     // ***** Pluggable L&F methods *****
  973.     // *********************************
  974.  
  975.     /**
  976.      * Notification from the UIFactory that the L&F
  977.      * has changed.
  978.      *
  979.      * @see JComponent#updateUI
  980.      */
  981.     public void updateUI() {
  982.         setUI((FileChooserUI)UIManager.getUI(this));
  983.  
  984.     uiFileView = getUI().getFileView();
  985.     boolean useAcceptAllFileFilter = removeChoosableFileFilter(getAcceptAllFileFilter());
  986.     if(useAcceptAllFileFilter) {
  987.         addChoosableFileFilter(getAcceptAllFileFilter());
  988.     }
  989.     }
  990.  
  991.     /**
  992.      * Returns a string that specifies the name of the L&F class
  993.      * that renders this component.
  994.      *
  995.      * @return "ButtonUI"
  996.      * @see JComponent#getUIClassID
  997.      * @see UIDefaults#getUI
  998.      * @beaninfo
  999.      *        expert: true
  1000.      *   description: A string that specifies the name of the L&F class.
  1001.      */
  1002.     public String getUIClassID() {
  1003.         return "FileChooserUI";
  1004.     }
  1005.  
  1006.     /**
  1007.      * Gets the UI object which implements the L&F for this component.
  1008.      *
  1009.      * @return the FileChooserUI object that implements the FileChooserUI L&F
  1010.      */
  1011.     public FileChooserUI getUI() {
  1012.         return (FileChooserUI) ui;
  1013.     }
  1014.  
  1015.  
  1016. }
  1017.